/*
 * Ingenic IMP System Control module implement.
 *
 * Copyright (C) 2014 Ingenic Semiconductor Co.,Ltd
 * Author: Zoro <ykli@ingenic.cn>
 */

#include <stdio.h>
#include <string.h>
#include <time.h>

#include <constraints.h>
#include <imp/imp_log.h>
#include <imp/imp_system.h>

#include <system/module.h>
#include <system/group.h>
#include <system/system.h>
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
#define TAG "System"

int IMP_System_Init(void)
{
	IMP_LOG_DBG(TAG, "%s SDK Version:%s-%s built: %s %s\n",
			__func__, CONFIG_SDK_VERSION, CONFIG_SDK_GIT_VERSION, __DATE__, __TIME__);
	return system_init();
}

int IMP_System_Exit(void)
{
	IMP_LOG_DBG(TAG, "%s\n", __func__);
	return system_exit();
}

int64_t IMP_System_GetTimeStamp(void)
{
	return system_gettime(RAW);
}

int IMP_System_RebaseTimeStamp(int64_t basets)
{
	return system_rebasetime(basets);
}

uint32_t IMP_System_ReadReg32(uint32_t regAddr)
{
	uint32_t read_value;
	int ret = read_reg_32(regAddr, &read_value);

	if (ret < 0) {
		read_value = 0;
		IMP_LOG_ERR(TAG, "%s(): failed\n");
	}

	return read_value;
}

void IMP_System_WriteReg32(uint32_t regAddr, uint32_t value)
{
	int ret = write_reg_32(regAddr, value);

	if (ret < 0)
		IMP_LOG_ERR(TAG, "%s(): failed\n");
}

int IMP_System_GetVersion(IMPVersion *pstVersion)
{
	if (pstVersion == NULL)
		return -1;

	sprintf(pstVersion->aVersion, "IMP-%s", CONFIG_SDK_VERSION);
	return 0;
}

int IMP_System_Bind(IMPCell *srcCell, IMPCell *dstCell)
{
	if (srcCell == NULL) {
		IMP_LOG_ERR(TAG, "%s(): src channel is NULL\n", __func__);
		return -1;
	}
	if (dstCell == NULL) {
		IMP_LOG_ERR(TAG, "%s(): dst channel is NULL\n", __func__);
		return -1;
	}

	return system_bind(srcCell, dstCell);
}

int IMP_System_UnBind(IMPCell *srcCell, IMPCell *dstCell)
{
	if (srcCell == NULL) {
		IMP_LOG_ERR(TAG, "%s(): src channel is NULL\n", __func__);
		return -1;
	}
	if (dstCell == NULL) {
		IMP_LOG_ERR(TAG, "%s(): dst channel is NULL\n", __func__);
		return -1;
	}

	return system_unbind(srcCell, dstCell);
}

int IMP_System_GetBindbyDest(IMPCell *dstCell, IMPCell *srcCell)
{
	if (dstCell == NULL) {
		IMP_LOG_ERR(TAG, "%s(): dst channel is NULL\n", __func__);
		return -1;
	}

	if (srcCell == NULL) {
		IMP_LOG_ERR(TAG, "%s(): src channel is NULL\n", __func__);
		return -1;
	}

	return system_get_bind_src(dstCell, srcCell);
}

const char* IMP_System_GetCPUInfo(void)
{
#if 0
	typedef enum {
		SOC_UNKNOWN = -1,
		SOC_T10_START = 0,
		SOC_T10_NORMAL = SOC_T10_START,
		SOC_T10_LITE,
		SOC_T10_LITE_V2,
		SOC_T10_END = SOC_T10_LITE_V2,
		SOC_T20_START,
		SOC_T20_NORMAL = SOC_T20_START,
		SOC_T20_LITE,
		SOC_T20_X,
		SOC_T20_END = SOC_T20_X,
		SOC_T30_START,
		SOC_T30_LITE = SOC_T30_START,
		SOC_T30_N,
		SOC_T30_X,
		SOC_T30_A,
		SOC_T30_Z,
		SOC_T30_END = SOC_T30_Z,
	} IMPCPUID;
#endif
	static char *cpu_info_array[] = {
		[SOC_T10_NORMAL] = "T10",
		[SOC_T10_LITE] = "T10-Lite",
		[SOC_T20_NORMAL] = "T20",
		[SOC_T20_LITE] = "T20-Lite",
		[SOC_T20_X] = "T20-X",
		[SOC_T30_LITE] = "T30-Lite",
		[SOC_T30_N] = "T30",
		[SOC_T30_N] = "T30-N",
		[SOC_T30_X] = "T30-X",
		[SOC_T30_A] = "T30-A",
		[SOC_T30_Z] = "T30-Z",
		[SOC_T21_L] = "T21-L",
		[SOC_T21_N] = "T21-N",
		[SOC_T21_X] = "T21-X",
		[SOC_T21_Z] = "T21-Z",
		[SOC_T23_N] = "T23-N",
		[SOC_T23_ZN] = "T23-ZN",
		[SOC_T23_ZX] = "T23-ZX",
		[SOC_T23_DL] = "T23-DL",
		[SOC_T23_DN] = "T23-DN",
		[SOC_T23_X] = "T23-X",
	};
	IMPCPUID cpu_id = get_cpu_id();
	if (cpu_id == SOC_T10_NORMAL) {
		return cpu_info_array[SOC_T10_NORMAL];
	} else if ((cpu_id == SOC_T10_LITE) || (cpu_id == SOC_T10_LITE_V2)) {
		return cpu_info_array[SOC_T10_LITE];
	} else if (cpu_id == SOC_T20_NORMAL) {
		return cpu_info_array[SOC_T20_NORMAL];
	} else if (cpu_id == SOC_T20_LITE) {
		return cpu_info_array[SOC_T20_LITE];
	} else if (cpu_id == SOC_T20_X) {
		return cpu_info_array[SOC_T20_X];
	} else if (cpu_id == SOC_T30_LITE) {
		return cpu_info_array[SOC_T30_LITE];
	} else if (cpu_id == SOC_T30_N) {
		return cpu_info_array[SOC_T30_N];
	} else if (cpu_id == SOC_T30_X) {
		return cpu_info_array[SOC_T30_X];
	} else if (cpu_id == SOC_T30_A) {
		return cpu_info_array[SOC_T30_A];
	} else if (cpu_id == SOC_T30_Z) {
		return cpu_info_array[SOC_T30_Z];
	} else if (cpu_id == SOC_T21_L) {
		return cpu_info_array[SOC_T21_L];
	} else if (cpu_id == SOC_T21_N) {
		return cpu_info_array[SOC_T21_N];
	} else if (cpu_id == SOC_T21_X) {
		return cpu_info_array[SOC_T21_X];
	} else if (cpu_id == SOC_T21_Z) {
		return cpu_info_array[SOC_T21_Z];
	} else if (cpu_id == SOC_T23_N) {
		return cpu_info_array[SOC_T23_N];
	} else if (cpu_id == SOC_T23_ZN) {
		return cpu_info_array[SOC_T23_ZN];
	} else if (cpu_id == SOC_T23_ZX) {
		return cpu_info_array[SOC_T23_ZX];
	} else if (cpu_id == SOC_T23_DL) {
		return cpu_info_array[SOC_T23_DL];
	} else if (cpu_id == SOC_T23_DN) {
		return cpu_info_array[SOC_T23_DN];
	} else if (cpu_id == SOC_T23_X) {
		return cpu_info_array[SOC_T23_X];
	}
	return "Unknown";
}

char *IMPPixfmtToString(IMPPixelFormat pixfmt)
{
	return pixfmt_to_string(pixfmt);
}

int IMP_System_MemPoolRequest(int poolId, size_t size, char *name)
{
    return IMP_MemPool_InitPool(poolId, size, name);
}
